﻿using System;
using KuiHuaBaoDian.Services.Battle.Data;

namespace KuiHuaBaoDian.Services.Battle {

    /// <summary>
    /// 战斗属性
    /// </summary>
    public interface IReadOnlyBattleAttributes : IPoolObject {

        IBattleAttributes AsReadWrite();

        IBattleBuffApplier AsBuffApplier();

        /// <summary>
        /// 生命值上限
        /// </summary>
        IReadOnlyBattleData HPMax { get; }

        /// <summary>
        /// 当前生命值
        /// </summary>
        IReadOnlyBattleData HP { get; }

        /// <summary>
        /// 攻击力
        /// </summary>
        IReadOnlyBattleData Attack { get; }

        /// <summary>
        /// 对精英的额外攻击加成
        /// </summary>
        IReadOnlyBattleData AttackBossAdditional { get; }

        /// <summary>
        /// 攻击速度
        /// </summary>
        IReadOnlyBattleData AttackSpeed { get; }

        /// <summary>
        /// 攻击冷却
        /// </summary>
        IReadOnlyBattleData CoolDown { get; }

        /// <summary>
        /// 暴击率
        /// </summary>
        IReadOnlyBattleData Critical { get; }

        /// <summary>
        /// 暴击伤害强度
        /// </summary>
        IReadOnlyBattleData CriticalPower { get; }

        /// <summary>
        /// 索敌范围
        /// </summary>
        IReadOnlyBattleData SpottingRange { get; }

        /// <summary>
        /// 防御
        /// </summary>
        IReadOnlyBattleData Defense { get; }

        /// <summary>
        /// 闪避
        /// </summary>
        IReadOnlyBattleData Dodge { get; }

        /// <summary>
        /// 移动速度
        /// </summary>
        IReadOnlyBattleData MoveSpeed { get; }

        /// <summary>
        /// 发起攻击总数
        /// </summary>
        IReadOnlyIntData AttackLaunchCount { get; }

        /// <summary>
        /// 按生命值上限伤害
        /// </summary>
        IReadOnlyBattleData DamageHPMax { get; }

        /// <summary>
        /// 按当前生命值伤害
        /// </summary>
        IReadOnlyBattleData DamageHP { get; }

        /// <summary>
        /// 附加伤害
        /// </summary>
        IReadOnlyBattleData Damage { get; }
    }

    public interface IBattleAttributes : IReadOnlyBattleAttributes {

        /// <summary>
        /// 生命值上限
        /// </summary>
        new IBattleComplexData HPMax { get; }

        /// <summary>
        /// 当前生命值
        /// </summary>
        new IBattleData HP { get; }

        /// <summary>
        /// 攻击力
        /// </summary>
        new IBattleComplexData Attack { get; }

        /// <summary>
        /// 对精英的额外攻击加成
        /// </summary>
        new IBattleComplexData AttackBossAdditional { get; }

        /// <summary>
        /// 攻击速度
        /// </summary>
        new IBattleComplexData AttackSpeed { get; }

        /// <summary>
        /// CD
        /// </summary>
        new IBattleComplexData CoolDown { get; }

        /// <summary>
        /// 暴击率
        /// </summary>
        new IBattleComplexData Critical { get; }

        /// <summary>
        /// 暴击伤害强度
        /// </summary>
        new IBattleComplexData CriticalPower { get; }

        /// <summary>
        /// 索敌范围
        /// </summary>
        new IBattleComplexData SpottingRange { get; }

        /// <summary>
        /// 移动速度
        /// </summary>
        new IBattleComplexData MoveSpeed { get; }

        /// <summary>
        /// 防御
        /// </summary>
        new IBattleComplexData Defense { get; }

        /// <summary>
        /// 闪避
        /// </summary>
        new IBattleComplexData Dodge { get; }

        /// <summary>
        /// 发起攻击总数
        /// </summary>
        new IIntData AttackLaunchCount { get; }

        /// <summary>
        /// 按生命值上限伤害
        /// </summary>
        new IBattleComplexData DamageHPMax { get; }

        /// <summary>
        /// 按当前生命值伤害
        /// </summary>
        new IBattleComplexData DamageHP { get; }

        /// <summary>
        /// 附加伤害
        /// </summary>
        new IBattleComplexData Damage { get; }
    }

    [Implement(typeof(IBattleAttributes))]
    internal sealed class BattleAttributes : KHBD_PoolObject, IBattleAttributes, IBattleBuffApplier {

        public IBattleAttributes AsReadWrite() => this;

        public IBattleBuffApplier AsBuffApplier() => this;

        private IBattleComplexData m_HPMax;
        public IReadOnlyBattleData HPMax => m_HPMax;
        IBattleComplexData IBattleAttributes.HPMax => m_HPMax;

        private IBattleData m_HP;
        public IReadOnlyBattleData HP => m_HP;
        IBattleData IBattleAttributes.HP => m_HP;

        private IBattleComplexData m_MoveSpeed;
        public IReadOnlyBattleData MoveSpeed => m_MoveSpeed;
        IBattleComplexData IBattleAttributes.MoveSpeed => m_MoveSpeed;

        private IBattleComplexData m_Defense;
        public IReadOnlyBattleData Defense => m_Defense;
        IBattleComplexData IBattleAttributes.Defense => m_Defense;

        private IBattleComplexData m_Dodge;
        public IReadOnlyBattleData Dodge => m_Dodge;
        IBattleComplexData IBattleAttributes.Dodge => m_Dodge;

        private IBattleComplexData m_CoolDown;
        public IReadOnlyBattleData CoolDown => m_CoolDown;
        IBattleComplexData IBattleAttributes.CoolDown => m_CoolDown;

        private IBattleComplexData m_AttackSpeed;
        public IReadOnlyBattleData AttackSpeed => m_AttackSpeed;
        IBattleComplexData IBattleAttributes.AttackSpeed => m_AttackSpeed;

        private IBattleComplexData m_Attack;
        public IReadOnlyBattleData Attack => m_Attack;
        IBattleComplexData IBattleAttributes.Attack => m_Attack;

        private IBattleComplexData m_AttackBossAdditional;
        public IReadOnlyBattleData AttackBossAdditional => m_AttackBossAdditional;
        IBattleComplexData IBattleAttributes.AttackBossAdditional => m_AttackBossAdditional;

        private IBattleComplexData m_Critical;
        public IReadOnlyBattleData Critical => m_Critical;
        IBattleComplexData IBattleAttributes.Critical => m_Critical;

        private IBattleComplexData m_CriticalPower;
        public IReadOnlyBattleData CriticalPower => m_CriticalPower;
        IBattleComplexData IBattleAttributes.CriticalPower => m_CriticalPower;

        private IBattleComplexData m_SpottingRange;
        public IReadOnlyBattleData SpottingRange => m_SpottingRange;
        IBattleComplexData IBattleAttributes.SpottingRange => m_SpottingRange;

        private IIntData m_AttackLaunchCount;
        public IReadOnlyIntData AttackLaunchCount => m_AttackLaunchCount;
        IIntData IBattleAttributes.AttackLaunchCount => m_AttackLaunchCount;

        private IBattleComplexData m_DamageHPMax;
        public IReadOnlyBattleData DamageHPMax => m_DamageHPMax;
        IBattleComplexData IBattleAttributes.DamageHPMax => m_DamageHPMax;

        private IBattleComplexData m_DamageHP;
        public IReadOnlyBattleData DamageHP => m_DamageHP;
        IBattleComplexData IBattleAttributes.DamageHP => m_DamageHP;

        private IBattleComplexData m_Damage;
        public IReadOnlyBattleData Damage => m_Damage;
        IBattleComplexData IBattleAttributes.Damage => m_Damage;

        private bool m_IsInitialized = false;

        protected override void Allocate() {
            if (!m_IsInitialized) {
                m_IsInitialized = true;
                Initialize();
            }
        }

        private void Initialize() {
            m_HPMax = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_HP = KHBD.TypeMap.Instantiate<IBattleData>();
            m_MoveSpeed = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_Defense = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_Dodge = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_CoolDown = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_Attack = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_AttackSpeed = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_AttackBossAdditional = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_Critical = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_CriticalPower = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_SpottingRange = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_AttackLaunchCount = KHBD.TypeMap.Instantiate<IIntData>();
            m_DamageHPMax = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_DamageHP = KHBD.TypeMap.Instantiate<IBattleComplexData>();
            m_Damage = KHBD.TypeMap.Instantiate<IBattleComplexData>();
        }

        protected override void Release() {
            m_HPMax.Clear();
            m_MoveSpeed.Clear();
            m_Defense.Clear();
            m_Dodge.Clear();
            m_CoolDown.Clear();
            m_Attack.Clear();
            m_AttackSpeed.Clear();
            m_AttackBossAdditional.Clear();
            m_Critical.Clear();
            m_CriticalPower.Clear();
            m_SpottingRange.Clear();
            m_DamageHPMax.Clear();
            m_DamageHP.Clear();
            m_Damage.Clear();
        }

        void IBattleBuffApplier.AddBuff(IBattleBuffProvider buffProvider) {
            m_DamageHPMax.Base.Add(buffProvider.DamageHPMaxBase);
            m_DamageHPMax.Factor.Add(buffProvider.DamageHPMaxFactor);
            m_DamageHPMax.Additional.Add(buffProvider.DamageHPMaxAdditional);
            m_DamageHP.Base.Add(buffProvider.DamageHPBase);
            m_DamageHP.Factor.Add(buffProvider.DamageHPFactor);
            m_DamageHP.Additional.Add(buffProvider.DamageHPAdditional);
            m_Damage.Base.Add(buffProvider.DamageBase);
            m_Damage.Factor.Add(buffProvider.DamageFactor);
            m_Damage.Additional.Add(buffProvider.DamageAdditional);
            m_Attack.Base.Add(buffProvider.AttackBase);
            m_Attack.Factor.Add(buffProvider.AttackFactor);
            m_Attack.Additional.Add(buffProvider.AttackAdditional);
            m_AttackBossAdditional.Base.Add(buffProvider.AttackBossAdditionalBase);
            m_AttackBossAdditional.Factor.Add(buffProvider.AttackBossAdditionalFactor);
            m_AttackBossAdditional.Additional.Add(buffProvider.AttackBossAdditionalAdditional);
            m_AttackSpeed.Base.Add(buffProvider.AttackSpeedBase);
            m_AttackSpeed.Factor.Add(buffProvider.AttackSpeedFactor);
            m_AttackSpeed.Additional.Add(buffProvider.AttackSpeedAdditional);
            m_Critical.Base.Add(buffProvider.CriticalBase);
            m_Critical.Factor.Add(buffProvider.CriticalFactor);
            m_Critical.Additional.Add(buffProvider.CriticalAdditional);
            m_CriticalPower.Base.Add(buffProvider.CriticalPowerBase);
            m_CriticalPower.Factor.Add(buffProvider.CriticalPowerFactor);
            m_CriticalPower.Additional.Add(buffProvider.CriticalPowerAdditional);
            m_SpottingRange.Base.Add(buffProvider.SpottingRangeBase);
            m_SpottingRange.Factor.Add(buffProvider.SpottingRangeFactor);
            m_SpottingRange.Additional.Add(buffProvider.SpottingRangeAdditional);
            m_MoveSpeed.Base.Add(buffProvider.MoveSpeedBase);
            m_MoveSpeed.Factor.Add(buffProvider.MoveSpeedFactor);
            m_MoveSpeed.Additional.Add(buffProvider.MoveSpeedAdditional);
            m_Defense.Base.Add(buffProvider.DefenseBase);
            m_Defense.Factor.Add(buffProvider.DefenseFactor);
            m_Defense.Additional.Add(buffProvider.DefenseAdditional);
            m_Dodge.Base.Add(buffProvider.DodgeBase);
            m_Dodge.Factor.Add(buffProvider.DodgeFactor);
            m_Dodge.Additional.Add(buffProvider.DodgeAdditional);
        }

        void IBattleBuffApplier.RemoveBuff(IBattleBuffProvider buffProvider) {
            m_DamageHPMax.Base.Remove(buffProvider.DamageHPMaxBase);
            m_DamageHPMax.Factor.Remove(buffProvider.DamageHPMaxFactor);
            m_DamageHPMax.Additional.Remove(buffProvider.DamageHPMaxAdditional);
            m_DamageHP.Base.Remove(buffProvider.DamageHPBase);
            m_DamageHP.Factor.Remove(buffProvider.DamageHPFactor);
            m_DamageHP.Additional.Remove(buffProvider.DamageHPAdditional);
            m_Damage.Base.Remove(buffProvider.DamageBase);
            m_Damage.Factor.Remove(buffProvider.DamageFactor);
            m_Damage.Additional.Remove(buffProvider.DamageAdditional);
            m_Attack.Base.Remove(buffProvider.AttackBase);
            m_Attack.Factor.Remove(buffProvider.AttackFactor);
            m_Attack.Additional.Remove(buffProvider.AttackAdditional);
            m_AttackBossAdditional.Base.Remove(buffProvider.AttackBossAdditionalBase);
            m_AttackBossAdditional.Factor.Remove(buffProvider.AttackBossAdditionalFactor);
            m_AttackBossAdditional.Additional.Remove(buffProvider.AttackBossAdditionalAdditional);
            m_AttackSpeed.Base.Remove(buffProvider.AttackSpeedBase);
            m_AttackSpeed.Factor.Remove(buffProvider.AttackSpeedFactor);
            m_AttackSpeed.Additional.Remove(buffProvider.AttackSpeedAdditional);
            m_Critical.Base.Remove(buffProvider.CriticalBase);
            m_Critical.Factor.Remove(buffProvider.CriticalFactor);
            m_Critical.Additional.Remove(buffProvider.CriticalAdditional);
            m_CriticalPower.Base.Remove(buffProvider.CriticalPowerBase);
            m_CriticalPower.Factor.Remove(buffProvider.CriticalPowerFactor);
            m_CriticalPower.Additional.Remove(buffProvider.CriticalPowerAdditional);
            m_SpottingRange.Base.Remove(buffProvider.SpottingRangeBase);
            m_SpottingRange.Factor.Remove(buffProvider.SpottingRangeFactor);
            m_SpottingRange.Additional.Remove(buffProvider.SpottingRangeAdditional);
            m_MoveSpeed.Base.Remove(buffProvider.MoveSpeedBase);
            m_MoveSpeed.Factor.Remove(buffProvider.MoveSpeedFactor);
            m_MoveSpeed.Additional.Remove(buffProvider.MoveSpeedAdditional);
            m_Defense.Base.Remove(buffProvider.DefenseBase);
            m_Defense.Factor.Remove(buffProvider.DefenseFactor);
            m_Defense.Additional.Remove(buffProvider.DefenseAdditional);
            m_Dodge.Base.Remove(buffProvider.DodgeBase);
            m_Dodge.Factor.Remove(buffProvider.DodgeFactor);
            m_Dodge.Additional.Remove(buffProvider.DodgeAdditional);
        }
    }
}
